#!/usr/bin/python
# -*- coding:UTF-8 -*-
# @Time    : 2019/1/7 9:16
# @Author  : 王志鹏
# @Site    : 
# @File    : Interface_test.py
# @Software: PyCharm
from plan_util import *
import threading
import time


def runTime(level=True):
    def wrapper(func):
        def inner_wrapper(*args, **kwargs):
            startTime = time.clock()  # 开始时间
            u = func(*args, **kwargs)
            endTime = time.clock()
            timeDifference = str(endTime - startTime)  # 时间差
            if level:
                print "%s方法:用时%s秒" % (func.__name__, timeDifference[0:5])
            return u

        return inner_wrapper

    return wrapper


def logs(level="debug", paths=""):
    def wrapper(func):
        def inner_wrapper(self, *args, **kwargs):

            u = func(self, *args, **kwargs)
            tempPath = tempfile.gettempdir()
            errPath = tempPath + "/logs.log"
            path = errPath if paths == "" else paths

            # print path
            if type(u) == requests.models.Response:
                t = threading.currentThread()
                util = Util()
                errorCode = u.json()["errorCode"]
                deploy = {
                    "threadName": threading.currentThread().getName(),
                    "time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                    "url": self.url,
                    "hader": self.hader,
                    "params": self.params,
                    "errorCode": errorCode,
                    "Response": u,
                    "content": u.content,
                    "text": u.text,
                }

                if level == "debug":
                    strs = "{time}--{threadName}--{Response}--{text}{url}\n{hader}\n{params}\n{content}\n".format(**deploy)

                elif level == "info":
                    strs = "{time}--{threadName}--{Response}".format(**deploy)

                elif level == "Error":
                    if errorCode == 110000:
                        strs = "{time}--{threadName}--{Response}\t{text}{url}\n{hader}\n{params}\n{content}".format(**deploy)

                elif level == "warn":
                    if errorCode != 0 and errorCode != 110000:
                        strs = "{time}--{threadName}--{Response}--{text}".format(**deploy)

                util.writeFile(path, strs)

            del util
            return u

        return inner_wrapper

    return wrapper


class Interface_test(Util):
    def __init__(self):
        # 初始化必要
        self.threadLock = threading.Lock()  # 锁 初始化
        self.flas = True  # 严格模式 循环开关
        self.count = 1  # 严格模式 计数器
        self.threads = []  # 线程池

        # 用户设定参数
        self.excuteNum = 0  # 设置总执行数量
        self.hader = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko'}  # 默认请求头
        self.url = ""
        self.params = {}

    def getConfig(self, path=""):
        modernFilePath = os.path.realpath(__file__)
        configPath = "%s/%s" % (os.path.dirname(modernFilePath), "config.json")
        config = path if path != "" else configPath
        config = json.load(open(config))
        return config

    def getAuthentication(self, _userid="FL-00479", _code="baitianyu", _secret="0C7134AAC334FBD88AAC850E51F2CE69"):

        config = self.getConfig()
        # url = 'http://192.168.5.23/requestAuthCode.do'
        url = "%s/requestAuthCode.do" % config.get("mthost")
        param_dict = {
            "userId": "FL-08112",
            "code": _code,
            "secret": _secret
        }
        res = self.post(url, param_dict, self.hader).json()

        if res.has_key("authentication") and res.get("errorCode") == 0:

            return res["authentication"]
        else:
            return ""

    def setHader(self, hader):
        self.hader = hader

    def setUrl(self, url):
        self.url = url

    def setParams(self, params={}, purview=True):

        # 默认填充权限码
        if purview:
            params[u"authentication"] = self.getAuthentication()

        self.params = params

    # 开启线程
    def startThreads(self):
        for t in self.threads:
            t.start()

    # 等待线程全部执行完毕
    def joinThreads(self):
        for t in self.threads:
            t.join()

    # 开启并等待线程结束
    def startAndJoinThreads(self):
        self.startThreads()
        self.joinThreads()

    def run(self, frequency, lock, type):

        if type:
            # 均衡模式 可自定义是否加锁,自动均匀分配线程执行数量
            for i in range(frequency):

                if lock:
                    self.threadLock.acquire()  # 加锁 保证执行TodoSomeThings的完整性, 未加锁 ,可高并发

                self.todoSomeThings()  # TODO

                if lock:
                    self.threadLock.release()  # 释放锁
        else:

            # 严格模式 必须加锁来 保证'计数器'和'TodoSomeThings'的完整性
            while self.flas:
                self.threadLock.acquire()  # 加锁

                self.todoSomeThings()  # TODO

                self.count = self.count + 1
                if 1 == self.excuteNum:
                    self.flas = False
                if self.count == self.excuteNum:  # 计数 要执行的总次数
                    self.flas = False

                self.threadLock.release()  # 释放锁

    def setThreads(self, excuteNum, threads, daemon=True, lock=True, type=False):
        """
        :param excuteNum: 执行数量
        :param threads: 线程数量
        :param daemon: 守护 默认开启 True
        :param lock: 锁 默认开启 True
        :param type: 均衡模式(True) 可自定义是否加锁,自动均匀分配线程执行数量
                    严格模式(False) 默认加锁以保证'计数器'和'TodoSomeThings'的完整性 默认
        :return: None
        """
        if type:
            frequency = excuteNum / threads  # 每个线程执行次数
            last = excuteNum % threads
            for i in range(threads):

                if i == threads - 1:  # 为最后一个线程增加 执行数量的余数
                    frequency = frequency + last

                creatThreads = threading.Thread(target=self.run, args=(frequency, lock, type))  # 创建线程

                creatThreads.setDaemon(daemon)  # 设置保护
                creatThreads.setName("CT_%s" % i)  # 设置线程名称

                self.threads.append(creatThreads)
        else:

            if self.excuteNum == 1:
                threads = 1

            for i in range(threads):
                creatThreads = threading.Thread(target=self.run, args=(None, None, type))  # 创建线程

                creatThreads.setDaemon(daemon)  # 设置保护
                creatThreads.setName("CT_%s" % i)  # 设置线程名称

                self.threads.append(creatThreads)

    # 调用接口,分析返回值等
    @logs(level="debug", paths="./InterfaceLogs.log")#生产日志,level="debug", paths="" 可指定级别,和路径,日志信息可自由配置
    @runTime(level=False)
    def todoSomeThings(self):
        # TODO
        # 可重写此方法以完成一整套请求测试动作
        res = self.post(self.url, self.params, self.hader)
        return res
        # 可分析返回值 生成日志 等

    @runTime(level=True)
    def main(self, excuteNum, threads):

        self.excuteNum = excuteNum

        url = "%s/addAccessories.do" % self.getConfig().get("host")
        # url = "%s/updatePlanForAdvance.do" % self.getConfig().get("host")
        params = {
            u"accessories.orderId": u"FL1812310007",
            u"accessories.supervisor.userId": u"---",
            u"accessories.fetchTime": u"2019-01-07",
            u"accessoriesItems[0].goods.gid": u"637",
            u"accessoriesItems[0].num": u"3"
        }
        self.setUrl(url)
        self.setParams(params)

        # self.setThreads(excuteNum, threads)  # 设置线程 加锁 严格模式 数量无分配线程抢占 优点,其中一个线程挂掉,保证执行数量
        self.setThreads(excuteNum, threads, daemon=True, lock=True, type=True)  # 均衡模式1 加锁 线程分配数量均衡
        # self.setThreads(excuteNum, threads, daemon=True, lock=False, type=True)  # 均衡模式1 不加锁 线程分配数量均衡 速度快 并发高

        self.startAndJoinThreads()  # 开启所有线程并等待执行完毕!


if __name__ == "__main__":
    # excuteNum = sys.argv[1] # 执行数量
    # threads = sys.argv[1] # 设置线程数量
    excuteNum = 10
    threads = 3

    interface_test = Interface_test()
    interface_test.main(int(excuteNum), int(threads))
